package org.redmagic.client;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.redmagic.client.api.Location;
import org.redmagic.client.utils.DocumentUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.google.gson.Gson;

public class WebLocation implements Location {

	private static final Log LOG = LogFactory.getLog(WebLocation.class);
	
	private URI uri;
	
	private List<List<String>> hierarchy;
	
	private WebLocation(URI uri) {
		
		this.uri = uri;
		hierarchy = new ArrayList<List<String>>();
	}
	
	@Override
	public URI getUri() {
		return uri;
	}

	@Override
	public List<List<String>> getHierarchy() {
		return hierarchy;
	}

	public void addAttempt(List<String> attempt) {
		hierarchy.add(attempt);
	}
	
	public Map<String, String> updateProperties(Set<String> properties) {
		
		JSONObject jsonObject = null;
		
		try {
			jsonObject = new JSONObject();
			jsonObject.put("hierarchy", hierarchy);
			jsonObject.put("properties", properties);
		} catch (Exception e) {
			throw new RuntimeException("Failed to create json object", e);
		}
		
		return sendRequestToService(jsonObject.toString());
	}
	
	private Map<String, String> sendRequestToService(String requestMessage) {
		
		HttpClient client = null;
		String responseJson = null;
		
		try {
			HttpPost post = new HttpPost(uri);
			post.removeHeaders("Accept");
			post.addHeader("Accept", "*/*");
			post.setEntity(new StringEntity(requestMessage));
	
	        client = new DefaultHttpClient();
	        HttpResponse response = client.execute(post);
	        
	        int statusCode = response.getStatusLine().getStatusCode();
	        responseJson = EntityUtils.toString(response.getEntity());
	        if (statusCode >= 200 && statusCode < 300) {
	            LOG.info("Success: " + responseJson);
	        } else {
	        	LOG.warn("Failure - " + statusCode + ": " + response.getStatusLine().getReasonPhrase());
	        }
		} catch (Exception e) {
			
		}
		
		if (client != null) {
			ClientConnectionManager ccm = client.getConnectionManager();
			if (ccm != null) {
				ccm.shutdown();
			}
		}
		
		if (responseJson == null) {
			return new HashMap<String, String>();
		} else {
			
			Gson gson = new Gson();
			@SuppressWarnings("unchecked")
			Map<String, String> response = gson.fromJson(responseJson, Map.class);
			return response;
		}
	}
	
	public static Location parseWebLocation(Element webLocation) {
		
		WebLocation location = null;
		URI uri = null;
		
		try {
			uri = new URI(webLocation.getAttribute("uri"));
			location = new WebLocation(uri);
		} catch (URISyntaxException e) {

			throw new RuntimeException("Unable to create web location with uri: " + uri);
		}

		// Parse the attempts to create the hierarchy
		NodeList attempts = webLocation.getElementsByTagName("attempt");
		for (int i = 0; i < attempts.getLength(); i++) {
			
			location.addAttempt(DocumentUtils.parseAttempt((Element) attempts.item(i)));
		}
		
		LOG.info(location.getHierarchy());
		
		return location;
	}
}
